package jfile

import (
	"bufio"
	"crypto/md5"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/text/encoding/unicode"
	"golang.org/x/text/transform"
)

// ReadFile 读取文件
// /
// 将文件内容读取到内存中,并返回数组指针
// 支持将非UTF-8编码的文件转换为UTF-8编码
func ReadFile2(filePath string) (*[]string, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	// 使用 UTF-8 转换器包装文件读取器，确保内容是 UTF-8 格式
	decoder := unicode.UTF8.NewDecoder()
	reader := transform.NewReader(file, decoder)

	var lines []string
	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return &lines, nil
}

// GetMd5 获取文件的MD5值
func GetMd5(filePath string) (string, error) {
	// 打开文件
	file, err := os.Open(filePath)
	if err != nil {
		return "", fmt.Errorf("failed to open file: %v", err)
	}
	defer file.Close()

	// 创建MD5哈希器
	hash := md5.New()

	// 将文件内容拷贝到哈希器中
	if _, err := io.Copy(hash, file); err != nil {
		return "", fmt.Errorf("failed to calculate MD5: %v", err)
	}

	// 计算MD5值并格式化为16进制字符串
	md5Sum := hash.Sum(nil)
	return fmt.Sprintf("%x", md5Sum), nil
}

// GetFileNameNoExt 获取文件名，不包含路径和文件类型后缀
func GetFileNameNoExt(path string) string {
	filename := filepath.Base(path)
	// 去除扩展名
	return strings.TrimSuffix(filename, filepath.Ext(filename))
}

// WriteLinesToFile
// 先判断文件是否存在，若存在，且比原文件大则覆盖，否则不处理
// 将字符串数组写入到文件中，每行一个字符串，覆盖文件，格式为utf-8
func WriteLinesToFile(lines *[]string, filePath string) (int64, error) {
	var fileSize int64 = 0
	// 判断文件是否存在，若存在，比较大小
	fileInfo, err := os.Stat(filePath)
	if err == nil {
		// 文件存在，比较大小
		var fileSize int64 = 0
		for _, line := range *lines {
			fileSize += int64(len(line)) + 1 // +1 for newline character
		}
		if fileInfo.Size() >= fileSize {
			// 原文件更大或相等，不处理
			return fileSize, nil
		}
	}

	// 创建或覆盖文件
	file, err := os.Create(filePath)
	if err != nil {
		return fileSize, err
	}
	defer file.Close()

	writer := bufio.NewWriter(file)
	for _, line := range *lines {
		_, err := writer.WriteString(line + "\n")
		if err != nil {
			return fileSize, err
		}
	}
	return fileSize, writer.Flush()
}
